package tabletask

import (
	"crypto/sha1"
	"encoding/hex"
	"errors"
	"io"
	"io/ioutil"
	"os"
	"strconv"
	"time"

	"github.com/astaxie/beego/logs"
	"github.com/astaxie/beego/orm"
	"github.com/xuri/excelize/v2"

	"cvevulner/cve-timed-task/db_models"
	"cvevulner/cve-timed-task/downloadfiletask"
	"cvevulner/cve-timed-task/util"
	"cvevulner/models"
)

func ImportDataTypeTwo() {
	ormModel := orm.NewOrm()
	filePath, dErr := downloadfiletask.HandleThree()
	if dErr != nil {
		logs.Error("downloadfiletask.HandleThree error:", dErr)
		return
	}
	files, rErr := ioutil.ReadDir(filePath)
	if rErr != nil {
		logs.Error(" ioutil.ReadDir error: ", rErr, filePath)
		return
	}

	for _, file := range files {
		fileName := file.Name()
		if file.IsDir() {
			logs.Warn(filePath+fileName, "is Dir, remove")
			_ = os.RemoveAll(filePath + fileName)
			continue
		}
		f, oErr := os.Open(filePath + fileName)
		if oErr != nil {
			continue
		}
		hash := sha1.New()
		_, cErr := io.Copy(hash, f)
		if cErr != nil {
			logs.Error("io.Copy :", cErr)
			_ = f.Close()
			continue
		}
		_ = f.Close()

		sum := hash.Sum(nil)
		hashValue := hex.EncodeToString(sum)
		logs.Info("open transaction")
		tranErr := ormModel.Begin()
		if tranErr != nil {
			logs.Error(" Open transaction error:", tranErr.Error())
			continue
		}
		list, rowsAffected, sErr := db_models.SelectCveFileHashByFileName(fileName, ormModel)
		if sErr != nil {
			logs.Error("db_models.SelectCveFileHashByFileName :", sErr)
			tranErr = ormModel.Rollback()
			if tranErr != nil {
				logs.Error(" Rollback transaction error:", tranErr.Error())
			}
			continue
		}
		if rowsAffected > 0 && util.InSlice(list, hashValue) {
			logs.Info("file has been parsed", fileName)
			tranErr = ormModel.Rollback()
			if tranErr != nil {
				logs.Error(" Rollback transaction error:", tranErr.Error())
			}
			_ = os.Remove(filePath + fileName)
			continue
		}
		sErr = db_models.InsertCveFileHash(fileName, hashValue, ormModel)
		if sErr != nil {
			logs.Error("db_models.InsertCveFileHash :", sErr)
			tranErr = ormModel.Rollback()
			if tranErr != nil {
				logs.Error(" Rollback transaction error:", tranErr.Error())
			}
			continue
		}
		tranErr = ormModel.Commit()
		if tranErr != nil {
			logs.Error(" Commit transaction error:", tranErr.Error())
			continue
		}

		excel, xErr := excelize.OpenFile(filePath + fileName)
		if xErr != nil {
			logs.Error("excelize.OpenReader:", xErr)
			continue
		}

		rows, gErr := excel.GetRows("Sheet1")
		if gErr != nil {
			logs.Error("excel.GetRows Sheet1 error: ", gErr)
			continue
		}
		now := time.Now().Format("2006-01-02 15:04:05")
		var packName string
		var version string
		var status int8
		var branchs string
		for _, row := range rows[1:] {
			if len(row) < 1 || row[0] == "" {
				continue
			}
			packName = row[0]
			if len(row) > 1 {
				version = row[1]
				if len(row) > 2 {
					s, err := strconv.ParseInt(row[2], 10, 8)
					if err != nil {
						status = 1
					} else {
						status = int8(s)
					}
					if len(row) > 3 {
						branchs = row[3]
					} else {
						branchs = ""
					}
				} else {
					status = 1
				}
			} else {
				version = ""
			}
			tranErr = ormModel.Begin()
			if tranErr != nil {
				logs.Error(" Open transaction error:", tranErr.Error())
				continue
			}

			_, wErr := db_models.SelectIssueRepoWhiteListByPackageName(row[0], ormModel)
			if wErr != nil {
				if errors.Is(orm.ErrNoRows, wErr) {
					wErr = db_models.InsertIssueRepoWhiteList(&models.IssueRepoWhitelist{
						PackageName: packName,
						Version:     version,
						Status:      status,
						Branchs:     branchs,
						CreateTime:  now,
					}, ormModel)
					if wErr != nil {
						logs.Error("db_models.InsertIssueRepoWhiteList:", wErr)
						tranErr = ormModel.Rollback()
						if tranErr != nil {
							logs.Error(" Rollback transaction error:", tranErr.Error())
						}
						continue
					}
				} else {
					logs.Error("db_models.SelectIssueRepoWhiteListByPackageName error: ", wErr)
					tranErr = ormModel.Rollback()
					if tranErr != nil {
						logs.Error(" Rollback transaction error:", tranErr.Error())
					}
					continue
				}
			} else {
				wErr = db_models.UpdateIssueRepoWhiteList(models.IssueRepoWhitelist{
					Status:      status,
					Branchs:     branchs,
					UpdateTime:  now,
					PackageName: packName,
					Version:     version,
				}, ormModel)
				if wErr != nil {
					logs.Error("db_models.UpdateIssueRepoWhiteList error:", wErr)
					tranErr = ormModel.Rollback()
					if tranErr != nil {
						logs.Error(" Rollback transaction error:", tranErr.Error())
					}
					continue
				}
			}
			tranErr = ormModel.Commit()
			if tranErr != nil {
				logs.Error(" Commit transaction error:", tranErr.Error())
				continue
			}
		}
		_ = os.Remove(filePath + fileName)
	}
}
